package com.d.lib.ui.view.progress;

import com.d.lib.ui.view.AttrUtils;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.BlurDrawLooper;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

/**
 * SettingProgressView
 * Created by D on 2016/7/7.
 */
public class SettingProgressView extends Component implements Component.DrawTask,
    Component.EstimateSizeListener, Component.TouchEventListener {
  private int mWidth;
  private int mHeight;

  private Paint mPaint;
  private Paint mPaintShader; // 用于绘制当前选中的渐变阴影
  private int mItemCount;
  private int mColorSelected;
  private int mColorUnselected;
  private float mRadiusSmall;
  private float mRadiusBig;
  private float mRadiusSpace;
  private float mLineHeight; // 中间连接线高度
  private float mShadeRadius; // 渐变阴影的宽度
  private float mItemWidth;
  private float mFirstItemRange;
  private float mBigRadiusWidth;
  private int mCurColor; // 当前选中的颜色
  private int mCurPosition;
  private int mClickPosition;
  private int mTouchSlop;
  private boolean mCanDrag;
  private boolean mIsClickValid; // 点击是否有效
  private float mDivX, mDivY; // 当前Move位置
  private float mLastX;
  private float mLastY;
  private OnProgressChangeListener mListener;

  public SettingProgressView(Context context) {
    super(context, null);
  }

  public SettingProgressView(Context context, AttrSet attrs) {
    this(context, attrs, 0);
  }

  public SettingProgressView(Context context, AttrSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);

    mItemCount = AttrUtils.getIntFromAttr(attrs, "lib_ui_view_spv_count", 5);
    mColorSelected = AttrUtils.getColorFromAttr(attrs, "lib_ui_view_spv_colorSelect",
        Color.getIntColor("#69B068"));
    mColorUnselected = AttrUtils.getColorFromAttr(attrs, "lib_ui_view_spv_colorUnselect",
        Color.GRAY.getValue());
    mRadiusSmall = AttrUtils.getDimensionFromAttr(attrs, "lib_ui_view_spv_radiusSmall",
        AttrHelper.fp2px(5, context));
    mRadiusBig = AttrUtils.getDimensionFromAttr(attrs, "lib_ui_view_spv_radiusBig",
        AttrHelper.fp2px(10, context));
    mRadiusSpace = AttrUtils.getDimensionFromAttr(attrs, "lib_ui_view_spv_radiusSpace",
        AttrHelper.fp2px(2, context));

    init(context);
    addDrawTask(this::onDraw);
    setEstimateSizeListener(this::onEstimateSize);
    setTouchEventListener(this::onTouchEvent);
  }

  /**
   * 设置选中颜色
   */
  public void setmColorSelected(int color) {
    mColorSelected = color;
  }

  /**
   * 设置未选中颜色
   */
  public void setmColorUnselected(int color) {
    mColorUnselected = color;
  }

  /**
   * 设置个数
   */
  public void setmItemCount(int count) {
    mItemCount = count;
  }

  /**
   * 设置大圆大小
   */
  public void setmRadiusBig(int size) {
    mRadiusBig = size;
  }

  /**
   * 设置小圆大小
   */
  public void setmRadiusSmall(int size) {
    mRadiusSmall = size;
  }

 /**
   * 设置圆
   */
  public void setmRadiusSpace(int space) {
    mRadiusSpace = space;
  }

  private void init(Context context) {
    mTouchSlop = 24;
    mLineHeight = AttrHelper.fp2px(2, context);
    mShadeRadius = AttrHelper.fp2px(5, context);
    mPaint = new Paint();
    mPaintShader = new Paint();
    mCurColor = Color.WHITE.getValue();
    mPaintShader.setColor(new Color(mCurColor));
    mPaintShader.setBlurDrawLooper(new BlurDrawLooper(mShadeRadius, 0, 0,
        new Color(mColorUnselected)));
  }

  @Override
  public void onDraw(Component component, Canvas canvas) {
    mPaint.setColor(new Color(mColorUnselected));
    mItemWidth = (mWidth - (mRadiusSpace + mRadiusBig) * 2) / (mItemCount - 1);
    float startx = mRadiusSpace + mRadiusBig;
    float starty = mHeight / 2 - mLineHeight / 2;
    float endx;
    float endy = starty + mLineHeight;
    if (mCanDrag) {
      endx = mDivX;
    } else {
      endx = mRadiusSpace + mRadiusBig + mItemWidth * mCurPosition;
    }
    canvas.drawRect(startx, starty, endx, endy, mPaint);

    mPaint.setColor(new Color(mColorSelected));
    canvas.drawRect(endx, starty, mWidth - mRadiusSpace - mRadiusBig, endy, mPaint);

    starty += mLineHeight / 2;
    for (int i = 0; i < mItemCount; i++) {
      startx = mRadiusBig + mRadiusSpace + mItemWidth * i;
      if (i == mCurPosition) {
        if (mCanDrag) {
          if (mDivX > startx) {
            drawCircle(canvas, mColorUnselected, startx, starty);
          } else if (mDivX < startx) {
            drawCircle(canvas, mColorSelected, startx, starty);
          }
          mPaint.setColor(new Color(mColorSelected));
          canvas.drawCircle(mDivX, starty, mRadiusBig + mRadiusSpace - mShadeRadius, mPaint);
        } else {
          canvas.drawCircle(startx, starty, mRadiusBig + mRadiusSpace - mShadeRadius, mPaintShader);
        }
      } else if (i < mCurPosition) {
        drawCircle(canvas, mColorUnselected, startx, starty);
      } else {
        drawCircle(canvas, mColorSelected, startx, starty);
      }
    }
  }

  /**
   * 绘制圆
   */
  private void drawCircle(Canvas canvas, int color, float startx, float starty) {
    mPaint.setColor(new Color(color));
    canvas.drawCircle(startx, starty, mRadiusSmall + mRadiusSpace, mPaint);
    mPaint.setColor(new Color(color));
    canvas.drawCircle(startx, starty, mRadiusSmall, mPaint);
  }

  @Override
  public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
    mWidth = EstimateSpec.getSize(widthMeasureSpec);
    mHeight = EstimateSpec.getSize(heightMeasureSpec);
    setEstimatedSize(EstimateSpec.getSizeWithMode(mWidth, EstimateSpec.PRECISE),
        EstimateSpec.getSizeWithMode(mHeight, EstimateSpec.PRECISE));
    return true;
  }

  @Override
  public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
    mFirstItemRange = mRadiusBig + mRadiusSpace + mItemWidth / 2;
    mBigRadiusWidth = (mRadiusBig + mRadiusSpace) * 2;
    int position = 0;
    switch (touchEvent.getAction()) {
      case TouchEvent.PRIMARY_POINT_DOWN:
        mLastX = mDivX = touchEvent.getPointerPosition(touchEvent.getIndex()).getX();
        mLastY = mDivY = touchEvent.getPointerPosition(touchEvent.getIndex()).getY();
        mClickPosition = -1;
        if (touchEvent.getPointerPosition(touchEvent.getIndex()).getX() < mBigRadiusWidth) {
          mClickPosition = 0;
        } else if (touchEvent.getPointerPosition(touchEvent.getIndex()).getX() >= mWidth - mBigRadiusWidth) {
          mClickPosition = mItemCount - 1;
        } else if (touchEvent.getPointerPosition(touchEvent.getIndex()).getX() >= mFirstItemRange) {
          mClickPosition =
              (int) ((touchEvent.getPointerPosition(touchEvent.getIndex()).getX() - mFirstItemRange) / mItemWidth) + 1;
          if (!(Math.abs(mBigRadiusWidth / 2 + mItemWidth * mClickPosition - touchEvent.getPointerPosition(touchEvent.getIndex()).getX()) <= mBigRadiusWidth / 2)) {
            mClickPosition = -1; // 未点中大圆范围内
          }
        }
        if (mClickPosition == mCurPosition) {
          mCanDrag = true;
          mIsClickValid = false; // 点击无效，交给ACTION_MOVE处理
          if (mDivX < mBigRadiusWidth / 2) {
            mDivX = mBigRadiusWidth / 2;
          }
          if (mDivX > mWidth - mBigRadiusWidth / 2) {
            mDivX = mWidth - mBigRadiusWidth / 2;
          }
          invalidate();
        } else {
          mCanDrag = false;
          mIsClickValid = true; // 点击有效，交给ACTION_UP处理
        }
        return true;
      case TouchEvent.POINT_MOVE:
        if (!mCanDrag) {
          return true;
        }
        // Disable parent view interception events
//                getComponentParent().requestDisallowInterceptTouchEvent(true);
        mDivX = touchEvent.getPointerPosition(touchEvent.getIndex()).getX();
        mDivY = touchEvent.getPointerPosition(touchEvent.getIndex()).getY();
        if (mDivX < mBigRadiusWidth / 2) {
          mDivX = mBigRadiusWidth / 2;
        }
        if (mDivX > mWidth - mBigRadiusWidth / 2) {
          mDivX = mWidth - mBigRadiusWidth / 2;
        }
        mIsClickValid = false; // 只要移动，点击无效，交给ACTION_UP处理
        if (touchEvent.getPointerPosition(touchEvent.getIndex()).getX() >= mWidth - mFirstItemRange) {
          position = mItemCount - 1;
        } else if (touchEvent.getPointerPosition(touchEvent.getIndex()).getX() >= mFirstItemRange) {
          position =
              (int) ((touchEvent.getPointerPosition(touchEvent.getIndex()).getX() - mFirstItemRange) / mItemWidth) + 1;
        }
        if (mCurPosition != position) {
          mCurPosition = position;
          if (mListener != null) {
            mListener.onProgressChange(mCurPosition);
          }
        }
        invalidate();
        return true;
      case TouchEvent.PRIMARY_POINT_UP:
        mCanDrag = false;
        if (!mIsClickValid) {
          invalidate();
          if (mListener != null) {
            mListener.onClick(mCurPosition);
          }
          return true;
        } else {
          if (Math.abs(touchEvent.getPointerPosition(touchEvent.getIndex()).getX() - mLastX) >= mTouchSlop || Math.abs(touchEvent.getPointerPosition(touchEvent.getIndex()).getY() - mLastY) >= mTouchSlop) {
            return true;
          }
        }
        if (touchEvent.getPointerPosition(touchEvent.getIndex()).getX() >= mWidth - mFirstItemRange) {
          position = mItemCount - 1;
        } else if (touchEvent.getPointerPosition(touchEvent.getIndex()).getX() >= mFirstItemRange) {
          position =
              (int) ((touchEvent.getPointerPosition(touchEvent.getIndex()).getX() - mFirstItemRange) / mItemWidth) + 1;
        }
        if (mCurPosition != position) {
          mCurPosition = position;
        }
        invalidate();
        if (mListener != null) {
          mListener.onClick(mCurPosition);
        }
        return true;
    }
    return true;
  }

  /**
   * 设置当前选中
   */
  public SettingProgressView setCurPosition(int curPosition) {
    this.mCurPosition = curPosition;
    return this;
  }

  public void setOnProgressChangeListener(OnProgressChangeListener listener) {
    this.mListener = listener;
  }

  public interface OnProgressChangeListener {

    /**
     * @param position From 0 to item count - 1
     */
    void onProgressChange(int position);

    /**
     * @param position from 0 to item count - 1
     */
    void onClick(int position);
  }
}
